<template>
  <!-- 词云 -->  
  <div class="wordCloudContainer">
    <div class="wordCloud__tagBall" :style="{ width: `${this.width}px`, height: `${this.height}px` }" @mouseenter="stop" @mouseleave="start">
      <span
        v-for="(item, index) of data"
        :key="index"
        class="wordCloud__tag"
        :style="{
          color: color[index % color.length],
          ...contentEle[index].style
        }"
        :title="item.name + item.value"
        >{{ item.name }}</span
      >
    </div>
  </div>
</template>

<script>
import { mapState } from 'vuex'
export default {
  name: 'CloudWork',
  props: {
    width: {
      type: Number,
      default: 350
    },
    height: {
      type: Number,
      default: 260
    },
    // 测试数据
    dataList: {
      type: Array,
      default: () => [
        {
          label: '劳动和社会保障',
          cellContent: 30
        }
      ]
    },
    color: {
      type: Array,
      default: () => ['rgba(0, 196, 255,.8)']
    }
  },
  data() {
    return {
      contentEle: [],
      direction: '-1',
      speed: 3000,
      animateID: null,
      data: [],
      timer: ''
    }
  },
  watch: {
    department: {
      handler(val, oldVal) {
        if (val !== oldVal) {
          console.log(this.timer)
          if (this.timer) {
            clearTimeout(this.timer)
          }
          this.timer = setTimeout(() => {
            this.init()
          }, 1000)
        }
      },
      deep: true
    },
    dataList: {
      handler(val, oldVal) {
        if (val !== oldVal) {
          this.init()
        }
      },
      deep: true
    }
  },
  computed: {
    ...mapState('department', ['department'])
  },
  mounted() {
    this.init()
  },
  methods: {
    init() {
      this.data = this.dataList.map(item => {
        return {
          name: item.label,
          value: item.cellContent,
          style: {}
        }
      })
      this.contentEle = this.data.map(() => ({
        x: 0,
        y: 0,
        z: 0,
        style: {}
      }))

      this.initChart()
    },
    initChart() {
      const RADIUSX = (this.width - 50) / 2
      const RADIUSY = (this.height - 50) / 2
      this.contentEle = []
      for (let i = 0; i < this.data.length; i += 1) {
        const k = -1 + (2 * (i + 1) - 1) / this.data.length
        const a = Math.acos(k)
        const b = a * Math.sqrt(this.data.length * Math.PI)
        const x = RADIUSX * Math.sin(a) * Math.cos(b)
        const y = RADIUSY * Math.sin(a) * Math.sin(b)
        const z = RADIUSX * Math.cos(a)
        const singleEle = {
          x,
          y,
          z,
          style: {}
        }
        this.contentEle.push(singleEle)
      }
      this.animate()
    },
    animate() {
      this.rotateX()
      this.rotateY()
      this.move()
      this.animateID = window.requestAnimationFrame(this.animate)
    },
    rotateX() {
      const angleX = ['-1', '1'].includes(this.direction) ? Math.PI / Infinity : Math.PI / ((Number(this.direction) / 2) * Number(this.speed))
      const cos = Math.cos(angleX)
      const sin = Math.sin(angleX)

      this.contentEle = this.contentEle.map(t => {
        const y1 = t.y * cos - t.z * sin
        const z1 = t.z * cos + t.y * sin
        return {
          ...t,
          y: y1,
          z: z1
        }
      })
    },
    rotateY() {
      const angleY = ['-2', '2'].includes(this.direction) ? Math.PI / Infinity : Math.PI / (Number(this.direction) * Number(this.speed))
      const cos = Math.cos(angleY)
      const sin = Math.sin(angleY)
      this.contentEle = this.contentEle.map(t => {
        const x1 = t.x * cos - t.z * sin
        const z1 = t.z * cos + t.x * sin
        return {
          ...t,
          x: x1,
          z: z1
        }
      })
    },
    move() {
      const CX = this.width / 2
      const CY = this.height / 2
      this.contentEle = this.contentEle.map(singleEle => {
        const { x, y, z } = singleEle
        const fallLength = 500
        const RADIUS = (this.width - 50) / 2
        const scale = fallLength / (fallLength - z)
        const alpha = (z + RADIUS) / (2 * RADIUS)
        const left = `${x + CX - 15}px`
        const top = `${y + CY - 15}px`
        const transform = `translate(${left}, ${top}) scale(${scale})`
        const style = {
          ...singleEle.style,
          opacity: alpha + 0.5,
          zIndex: parseInt(scale * 100, 10),
          transform
        }
        return {
          x,
          y,
          z,
          style
        }
      })
    },
    // 鼠标移入暂停
    stop() {
      window.cancelAnimationFrame(this.animateID)
    },
    // 鼠标离开恢复
    start() {
      this.animate()
    }
  }
}
</script>

<style lang="scss"  scoped>
.wordCloudContainer {
  width: 100%;
  height: 100%;
  display: flex;
  justify-content: center;
  align-items: center;

  .wordCloud__tagBall {
    position: relative;
    overflow: hidden;
  }
  .wordCloud__tag {
    display: block;
    position: absolute;
    left: 0px;
    top: 0px;
    right: 0;
    text-decoration: none;
    font-family: MicrosoftYaHei;
    font-size: 18px;
    font-weight: normal;
    font-stretch: normal;
    letter-spacing: 1px;
    color: rgba(0, 234, 255, 1);
  }
  .wordCloud__tag :hover {
    // color: red;
  }
  .wordCloud__home {
    display: flex;
    justify-content: center;
  }
}
</style>
